﻿#include "KLTcpServer.h"

#include <algorithm>
#include <memory>

#ifdef _IMCTRACE
#pragma message (__LOC__ "#define _IMCTRACE")
#endif

void PrintLog(const char* str)
{
    std::ofstream outFile("D:\\chenning.txt", std::ios_base::app);
    if (outFile) {
        outFile << str << std::endl;
    }
}


#include "KLTcpServer.h"
#include <algorithm>

KLTcpServer::KLTcpServer() : m_sock(INVALID_SOCKET)
{
    PrintLog("Server constructor");
}

KLTcpServer::~KLTcpServer()
{
    PrintLog("Server destructor");
    Close();
    if (m_hProducerThread.joinable()) {
        m_hProducerThread.join();
    }
    if (m_hOnRunHandle.joinable()) {
        m_hOnRunHandle.join();
    }
}

SOCKET KLTcpServer::InitSocket()
{
#ifdef _WIN32
    WORD ver = MAKEWORD(2, 2);
    WSADATA dat;
    WSAStartup(ver, &dat);
#endif
    if (INVALID_SOCKET != m_sock) {
        Close();
    }
    m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == m_sock) {
        PrintLog("Error: Failed to create socket");
    }
    else {
        PrintLog("Socket created successfully");
    }
    return m_sock;
}

int KLTcpServer::Bind(const char* ip, unsigned short port)
{
    sockaddr_in _sin = {};
    _sin.sin_family = AF_INET;
    _sin.sin_port = htons(port);

#ifdef _WIN32
    if (ip) {
        _sin.sin_addr.S_un.S_addr = inet_addr(ip);
    }
    else {
        _sin.sin_addr.S_un.S_addr = INADDR_ANY;
    }
#else
    if (ip) {
        _sin.sin_addr.s_addr = inet_addr(ip);
    }
    else {
        _sin.sin_addr.s_addr = INADDR_ANY;
    }
#endif
    int ret = bind(m_sock, (sockaddr*)&_sin, sizeof(_sin));
    if (SOCKET_ERROR == ret) {
        PrintLog("Error: Failed to bind port");
    }
    else {
        PrintLog("Port bound successfully");
    }
    return ret;
}

int KLTcpServer::Listen(int n)
{
    int ret = ::listen(m_sock, n);
    if (SOCKET_ERROR == ret) {
        PrintLog("Error: Failed to listen on port");
    }
    else {
        PrintLog("Listening on port");
    }
    return ret;
}

SOCKET KLTcpServer::Accept()
{
    sockaddr_in clientAddr = {};
    int nAddrLen = sizeof(sockaddr_in);
    SOCKET cSock = INVALID_SOCKET;

#ifdef _WIN32
    cSock = ::accept(m_sock, (sockaddr*)&clientAddr, &nAddrLen);
#else
    cSock = accept(m_sock, (sockaddr*)&clientAddr, (socklen_t*)&nAddrLen);
#endif

    if (INVALID_SOCKET == cSock) {
        PrintLog("Error: Invalid client socket");
    }
    else {
        auto client = std::make_shared<KLClientSocket>(cSock);
        // 修改后
        client->setMessageCallback([this](SOCKET sock, const char* msg, size_t len) {
            this->OnNetMsg(sock, msg, len);
            });
        addClient(client);
        client->start();
        PrintLog("New client connected");
    }
    return cSock;
}

void KLTcpServer::addClient(std::shared_ptr<KLClientSocket> pClient)
{
    std::lock_guard<std::mutex> lock(m_clientMutex);
    _clients.push_back(pClient);
}

void KLTcpServer::removeClient(std::shared_ptr<KLClientSocket> pClient)
{
    std::lock_guard<std::mutex> lock(m_clientMutex);
    auto it = std::remove(_clients.begin(), _clients.end(), pClient);
    if (it != _clients.end()) {
        _clients.erase(it, _clients.end());
    }
}

void KLTcpServer::Start()
{
    m_hOnRunHandle = std::thread(&KLTcpServer::onRunThread, this);
}

void KLTcpServer::Close()
{
    if (m_sock != INVALID_SOCKET) {
        {
            std::lock_guard<std::mutex> lock(m_clientMutex);
            for (auto& client : _clients) {
                client->stop();
            }
            _clients.clear();
        }

#ifdef _WIN32
        closesocket(m_sock);
        WSACleanup();
#else
        close(m_sock);
#endif
        m_sock = INVALID_SOCKET;
    }
}

bool KLTcpServer::isRun() const
{
    return m_sock != INVALID_SOCKET;
}

bool KLTcpServer::OnRun()
{
    if (isRun()) {
        fd_set fdRead;
        FD_ZERO(&fdRead);
        FD_SET(m_sock, &fdRead);

        timeval t = { 0, 10 };
        int ret = select(m_sock + 1, &fdRead, 0, 0, &t);

        if (ret < 0) {
            PrintLog("Select task ended");
            Close();
            return false;
        }

        if (FD_ISSET(m_sock, &fdRead)) {
            FD_CLR(m_sock, &fdRead);
            Accept();
            return true;
        }
        return true;
    }
    return false;
}

// 修改 SendData 方法
int KLTcpServer::SendData(SOCKET cSock, const char* data, size_t len)
{
    if (isRun() && len > 0) {
        return send(cSock, data, len, 0);
    }
    return SOCKET_ERROR;
}
void KLTcpServer::SendDataToAll(const std::vector<char>& data)
{
    std::lock_guard<std::mutex> lock(m_clientMutex);
    for (auto& client : _clients) {
        SendData(client->sockfd(), data.data(), data.size());
    }
}
void KLTcpServer::OnLeave(std::shared_ptr<KLClientSocket> pClient)
{
    removeClient(pClient);
}

void KLTcpServer::OnNetMsg(SOCKET cSock, const char* data, size_t len)
{
    // 处理接收到的原始数据
    if (_messageCallback) {
        _messageCallback(cSock, data, len);
    }
    // 可以在这里添加具体的消息处理逻辑
    PrintLog("Received message from client");
}

void KLTcpServer::messgeSendThread()
{
    while (isRun()) {
        std::unique_lock<std::mutex> lock(m_sendMutex);
        m_EventSend.wait(lock, [this] {
            return !m_listMessgeToSend.empty() || !isRun();
            });

        if (!isRun()) break;

        // 获取消息数据（vector）
        auto data = std::move(m_listMessgeToSend.front());
        m_listMessgeToSend.pop_front();
        lock.unlock();

        // 发送数据
        SendDataToAll(data);
    }
}

void KLTcpServer::onRunThread()
{
    while (isRun()) {
        OnRun();
    }
}

void KLTcpServer::StartThread()
{
    m_hProducerThread = std::thread(&KLTcpServer::messgeSendThread, this);
}

// 新增的SendData实现（内部使用）
void KLTcpServer::SendData(const std::vector<char>& data)
{
    std::lock_guard<std::mutex> lock(m_sendMutex);
    m_listMessgeToSend.push_back(data);
    m_EventSend.notify_one();
}